﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using System.Runtime.InteropServices;

namespace CMS6Tools.Management
{
    public delegate void TFSIterationSelectedChanged(object sender, Node selectedValue);

    public partial class TFSIterationUserControl : UserControl
    {
        const string StageFieldReferenceName = "Vision.Stage";
        const string SeverityFieldReferenceName = "Microsoft.VSTS.Common.Severity";
        const string IterationPathFieldReferenceName = "System.IterationPath";
        const string ReleasePrefix = "Release ";
        const string TBDIterationName = "TBD";
        const string TagSourceCodeFolderath = "$/CMS 6/CMS 6/tags";
        readonly DateTime MinDateTime = new DateTime(2015, 1, 1);
        const float HoursAmount = 30.0F;

        public TFSIterationUserControl()
        {
            InitializeComponent();
            ShownLevel = 2;
            MultipleSelect = true;
        }

        private void SelectAllIterationCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            foreach (TreeNode treeNode in IterationTreeView.Nodes)
            {
                treeNode.Checked = SelectAllIterationCheckBox.Checked;
            }
        }

        private void ProjectComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (ProjectComboBox.SelectedIndex >= 0)
            {
                IterationTreeView.Nodes.Clear();
                var selectedProjectID = (int)((dynamic)ProjectComboBox.SelectedItem).Id;
                var workItemStore = Util.AuthenticatedTfsTeamProjectCollection.GetService<WorkItemStore>();
                var project = workItemStore.Projects.OfType<Project>().Where(a => a.Id == selectedProjectID).FirstOrDefault();
                if (project != null)
                {
                    var rootNodes = project.IterationRootNodes.OfType<Node>();
                    var level = 0;
                    level = BindIterationTreeView(IterationTreeView.Nodes, rootNodes, true, ShownLevel, level);
                    if (IterationTreeView.Nodes.Count > 0)
                        IterationTreeView.Nodes[0].EnsureVisible();
                }
            }
        }

        private int BindIterationTreeView(TreeNodeCollection treeNodeCollection, IEnumerable<Node> nodes, bool needCheckBox, int maxLevel, int currentLevel)
        {
            if (currentLevel == maxLevel)
                return currentLevel;

            var resultLevel = currentLevel;
            foreach (var node in nodes.OrderByDescending(a => a.Name))
            {
                if (node.Name.Equals(TBDIterationName, StringComparison.InvariantCultureIgnoreCase))
                    continue;

                if (node.Name.StartsWith("Release 2014"))
                    continue;

                var childTreeNode = new TreeNode(node.Name);
                childTreeNode.Tag = node;
                treeNodeCollection.Add(childTreeNode);
                if (!needCheckBox)
                    HideCheckBox(IterationTreeView, childTreeNode);
                if (node.HasChildNodes)
                {
                    var tempLevel = BindIterationTreeView(childTreeNode.Nodes, node.ChildNodes.OfType<Node>(), false, maxLevel, currentLevel + 1);
                    if (tempLevel > resultLevel)
                        resultLevel = tempLevel;
                    childTreeNode.ExpandAll();
                }
            }
            return resultLevel;
        }


        #region Interop
        private const int TVIF_STATE = 0x8;
        private const int TVIS_STATEIMAGEMASK = 0xF000;
        private const int TV_FIRST = 0x1100;
        private const int TVM_SETITEM = TV_FIRST + 63;

        [StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Auto)]
        private struct TVITEM
        {
            public int mask;
            public IntPtr hItem;
            public int state;
            public int stateMask;
            [MarshalAs(UnmanagedType.LPTStr)]
            public string lpszText;
            public int cchTextMax;
            public int iImage;
            public int iSelectedImage;
            public int cChildren;
            public IntPtr lParam;
        }

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam,
                                                 ref TVITEM lParam);

        /// <summary>
        /// Hides the checkbox for the specified node on a TreeView control.
        /// </summary>
        private void HideCheckBox(TreeView treeView, TreeNode node)
        {
            TVITEM tvi = new TVITEM();
            tvi.hItem = node.Handle;
            tvi.mask = TVIF_STATE;
            tvi.stateMask = TVIS_STATEIMAGEMASK;
            tvi.state = 0;
            SendMessage(treeView.Handle, TVM_SETITEM, IntPtr.Zero, ref tvi);
        }
        #endregion

        #region Load Event
        private void TFSIterationUserControl_Load(object sender, EventArgs e)
        {
        }
        #endregion

        #region Public Methods
        public void LoadTfs()
        {
            if (MultipleSelect)
            {
                SelectAllIterationCheckBox.Visible = true;
            }
            else
            {
                SelectAllIterationCheckBox.Visible = false;
                splitContainer2.SplitterDistance = 1;
            }

            var workItemStore = Util.AuthenticatedTfsTeamProjectCollection.GetService<WorkItemStore>();
            ProjectComboBox.ValueMember = "ID";
            ProjectComboBox.DisplayMember = "Name";
            ProjectComboBox.DataSource = workItemStore.Projects.OfType<Project>()
                //    .Select(a => new { 
                //    a.Name,
                //    a.Id,
                //    a.Uri
                //})
            .ToList(); 
        }
        #endregion

        #region Public Properties
        public int ShownLevel { get; set; }
        public bool MultipleSelect { get; set; }
        public event TFSIterationSelectedChanged SelectedChanged;
        public Node SelectedNode { get; private set; }
        #endregion

        #region IterationTreeView AfterSelect
        private void IterationTreeView_AfterSelect(object sender, TreeViewEventArgs e)
        {
        }

        private void DeselectNode(TreeNodeCollection nodes, TreeNode excluedNode)
        {
            foreach (TreeNode node in nodes)
            {
                if (node != excluedNode)
                {
                    node.Checked = false;
                }
            }
        }

        private void IterationTreeView_AfterCheck(object sender, TreeViewEventArgs e)
        {
            if (e.Node.Checked)
            {
                if (!MultipleSelect)
                {
                    DeselectNode(IterationTreeView.Nodes, e.Node);
                }
                SelectedNode = e.Node.Tag as Node;
                if (SelectedChanged != null)
                    SelectedChanged(sender, e.Node.Tag as Node);
            }
            else
            {
                if (e.Node.Tag as Node == SelectedNode)
                    SelectedNode = null;
            }
        }

        private void IterationTreeView_BeforeCheck(object sender, TreeViewCancelEventArgs e)
        { 
        }
        #endregion
    }
}
